//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;

namespace OpenLS.Spreadsheet
{
    class HashList<T>: IEnumerable<T>
    {
        public HashList()
        {

        }
        public HashList(IEnumerable<T> e)
        {
            foreach (T t in e)
                Add (t);
        }
        /// <summary>
        /// Adds a new item
        /// </summary>
        /// <param name="t"></param>
        /// <returns>true if the intem was added, false if the item was already there</returns>
        public bool Add(T t)
        {
            if (_table.ContainsKey(t))
            {
                return false;
            }
            _table.Add(t, t);
            _list.Add(t);
            return true;
        }
        public int Count
        {
            get
            {
                return _list.Count;
            }
        }

        readonly Dictionary<T, T> _table = new Dictionary<T, T>();
        readonly List<T> _list = new List<T>();

#if DEBUG
        [ContractInvariantMethod]
        private void ObjectInvariant()
        {
            Contract.Invariant(_list != null);
            Contract.Invariant(_table != null);
            Contract.Invariant(_table.Count == _list.Count);
        }
#endif
        public T this[int i]
        {
            get
            {
                Contract.Requires(i >= 0);
                Contract.Requires(i < Count);

                return _list[i]; 
            }
        }
        public T GetItem(T t)
        {
            Contract.Ensures(Contains(Contract.Result<T>()));
            T result;
            if (_table.TryGetValue(t, out result))
                return result;
            Add(t);
            return t;
        }
        public IEnumerator<T> GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        internal bool Contains(T t)
        {

            return _table.ContainsKey(t);
        }


        internal void Remove(T node)
        {
            _table.Remove(node);
            _list.Remove(node);
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}
